import datetime
from typing import Any
from sqlalchemy import INTEGER, Column, Engine, Select, Update, func, select, update
from sqlalchemy.orm import Mapped,Session,mapped_column,DeclarativeBase, Query,sessionmaker
from app import myApp
from app.utils.Idgenerator.generator import DefaultIdGenerator
from loguru import logger

class Modal(DeclarativeBase):
    __abstract__ = True
    _session:Session=None
    _engine:Engine=None
    _fieldIgnore:list=[]
    _idGenerator=None
    _idGeneratorType='db'    #snowflake 雪花算法 db 用数据库自身自增id
    def __del__(self):
        logger.info(self.__class__.__name__+" 正在销毁....")
        if self._session!=None:
            self._session.close()
    def __init__(self,*args,**kwargs):
        self.getSession()
        super().__init__(*args,**kwargs)

    def toDic(self):
        dic=vars(self)
        for key in dic.copy():
            if key.startswith("_") or key in self._fieldIgnore:
                del dic[key]
        return dic
    
    def toJson(self):
        dic=vars(self)
        newDic={}
        for key in dic.copy():
            if key.startswith("_") or key in self._fieldIgnore:
                continue
            value=dic[key]
            if value!=None:
                getAttrName='get'+key[0].upper()+key[1:]+'Attr'
                if hasattr(self,getAttrName):
                    getAttrMethod=getattr(self,getAttrName)
                    value=getAttrMethod(value)
            newDic[key]=value
        return newDic

    @staticmethod
    def createDatebaseTable():
        DeclarativeBase.metadata.create_all(myApp.dbEngine)
        
    @classmethod
    def get(cls,id=None,query:Query=None):
        session=Session(myApp.dbEngine)
        if query!=None:
            obj=query.with_session(session).first()
        else:
            obj=session.get(cls,id)
        if obj==None:
            return obj
        obj._session=session
        obj._engine=myApp.dbEngine
        return obj

    def getSession(self)->Session:
        if(self._session==None):
            self._session=Session(self.getEngine())
        return self._session
    
    def getEngine(self):
        if(self._engine==None):
            self._engine=myApp.dbEngine
        return self._engine
    
    def getIdGenerator(self)->DefaultIdGenerator :
        if(self._idGenerator==None):
            self._idGenerator=myApp.idGenerator
        return self._idGenerator
    
    def save(self):
        if self.id==None:
            if self._idGeneratorType=='snowflake':
                self.id=self.getIdGenerator().next_id()
            self.getSession().add(self)
        self.commit()
        
    
    def delete(self):
        self.getSession().delete(self)
    
    def commit(self):
        self.getSession().commit()
    
    def rollback(self):
        self.getSession().rollback()
    
    @classmethod
    def query(cls)->Query:
        cls._engine=myApp.dbEngine
        cls._session=Session(cls._engine)
        return Query(cls).with_session(cls._session)